package agh.rozproszony;

import Controller.AdminController;
import View.Welcome;
import agh.rozproszony.model.Invitation;
import agh.rozproszony.model.Reservation;
import agh.rozproszony.model.Room;
import agh.rozproszony.model.User;
import agh.rozproszony.reservations.ReservationEventListener;
import agh.rozproszony.reservations.ReservationsServer;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.List;
import javax.swing.UIManager;

public class MainRMIReservationsClient {

    private final static boolean URUCHOM_TYMCZASOWY_SERWER = true;

    public static void main(String[] args) throws Exception {

        for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Windows".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }

        try {
            testReservationServerInGUI();
            //testReservationServerInConsole();
            //testAdminPanel();
        } catch (Exception ex) {
            throw new RuntimeException("Blad RMI podczas testowania systemu rezerwacji", ex);
        }
    }

    public static void testReservationServerInGUI() {

        new Welcome().run();
    }

    public static void testAdminPanel() throws Exception {
        if (URUCHOM_TYMCZASOWY_SERWER) {
            System.out.println("=== Uruchamianie tymczasowego serwera rezerwacji RMI ===");
            RozproszonyServer.main(null); // Tymczasowe tworzenie serwera
        }

        RozproszonyConfiguration config = new RozproszonyConfiguration();
        config.printConfiguration();

        ReservationsServer server = (ReservationsServer) Naming.lookup(config.getRmiReservationServiceAddress());




        AdminController adminController = new AdminController(server);
        adminController.show();

    }

    public static void testReservationServerInConsole() throws Exception {
        if (URUCHOM_TYMCZASOWY_SERWER) {
            System.out.println("=== Uruchamianie tymczasowego serwera rezerwacji RMI ===");
            RozproszonyServer.main(null); // Tymczasowe tworzenie serwera
        }

        RozproszonyConfiguration config = new RozproszonyConfiguration();
        config.printConfiguration();

        System.out.println("=== Test klienta rezerwacji RMI w konsoli ===");

        ReservationsServer server = (ReservationsServer) Naming.lookup(config.getRmiReservationServiceAddress());

        testujRezerwacjeRMI(server);

        System.exit(0);
    }

    public static void testujRezerwacjeRMI(final ReservationsServer server) throws RemoteException {

        System.out.println("Rezerwacji w systemie: " + server.getAllReservations().size());

        System.out.println("Pobieranie uzytkownikow systemu");
        List<User> users = server.getAllUsers();

        for (User user : users) {
            System.out.println(user.getId() + " / " + user.getLogin() + " / " + user.getEmail());
        }

        System.out.println("Pobieranie sal w systemie");
        List<Room> rooms = server.getAllRooms();

        for (Room room : rooms) {
            System.out.println(room.getId() + " / " + room.getName());
        }

        for (int i = 0; i < 20; i++) {
            System.out.println("Losowanie uzytkownika rezerwujacego");
            User owner = users.get((int) (Math.random() * users.size()));

            System.out.println("Losowanie sali do rezerwacji");
            Room room = rooms.get((int) (Math.random() * rooms.size()));

            int year = 2013;
            int month = 6;
            int day = 1 + (int) (Math.random() * 3);

            int fromHour = (int) (Math.random() * 5) + 10;
            int toHour = fromHour + 1 + (int) (Math.random() * 5);

            System.out.println("Proba rezerwacji pokoju: " + room.getName() + " na dzien "
                    + year + "." + month + "." + day + " od " + fromHour + ":00 do " + toHour + ":00");

            Reservation newReservation = new Reservation(0, room.getId(), owner.getId(), year, month, day, fromHour, toHour);
            boolean success = server.addReservation(newReservation);
            if (success) {
                System.out.println("Rezerwacja powiodla sie");
            } else {
                System.out.println("Rezerwacja nie powiodla sie");
            }
        }

        System.out.println("===Rezerwacje w systemie ===");

        List<Reservation> reservations = server.getAllReservations();

        for (Reservation reservation : reservations) {
            System.out.println("* Rezerwacja ID: " + reservation.getId() + " ID Pokoju: "
                    + reservation.getRoomId() + " ID uzytkwonika: " + reservation.getOwnerId());
            System.out.println("Czas: " + reservation.getYear() + "." + reservation.getMonth()
                    + "." + reservation.getDay() + " od " + reservation.getFromHour() + ":00 do " + reservation.getToHour() + ":00");
        }

        System.out.println("Rezerwacji w systemie: " + server.getAllReservations().size());

        System.out.println("=== Rejestrowanie obserwatora zaproszen ===");

        ReservationEventListener testowyKlient = new ReservationEventListener() {
            private final static int FAKE_USER_ID = 5;

            @Override
            public void newInvitationArrived() throws RemoteException {
                System.out.println("Uzytkownik udawany odswieza GUI");
                List<Invitation> awaitingInvitations = server.getAwaitingInvitations(FAKE_USER_ID);
                for (Invitation awaitingInvitation : awaitingInvitations) {
                    System.out.println("Uzytkownik udawany widzi oczekujace zaproszenie, tytul:" + awaitingInvitation.getTitle());
                }
            }

            @Override
            public int getLoggedUserId() {
                return FAKE_USER_ID; // udawany uzytkownik
            }
        };

        ReservationEventListener stubTestowegoKlienta = (ReservationEventListener) UnicastRemoteObject.exportObject(testowyKlient, 0);
        server.addReservationEventListener(stubTestowegoKlienta);

        System.out.println("=== Wysylanie zaproszenia do udawanego uzytkownika ===");

        Reservation reservationToInvite = server.getAllReservations().get(0);
        Invitation newInvitation = new Invitation();
        newInvitation.setAccepted(false);
        newInvitation.setReservationId(reservationToInvite.getId());
        newInvitation.setTitle("Testowe zaproszenie");
        newInvitation.setUserId(5);

        server.addInvitation(newInvitation);

    }
}
